package com.example.spring.multi.module.minio;

import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.PutObjectOptions;
import io.minio.errors.InvalidEndpointException;
import io.minio.errors.InvalidExpiresRangeException;
import io.minio.errors.InvalidPortException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.InputStream;

/**
 * minIO工具类
 * @author think
 */
@Component
public class MinIoUtil {

    @Autowired
    private MinIoConfig minIo;

    private MinioClient instance;

    private static final int DEFAULT_EXPIRY_TIME = 7 * 24 * 3600;

    @PostConstruct
    public void init() {
        try {
            instance = new MinioClient(minIo.getEndpoint(),minIo.getAccessKey(),minIo.getSecretKey());
        } catch (InvalidPortException e) {
            e.printStackTrace();
        } catch (InvalidEndpointException e) {
            e.printStackTrace();
        }
    }

    /**
     * 判断 bucket是否存在
     * @param bucketName
     * @return
     */
    public boolean bucketExists(String bucketName){
        try {
            return instance.bucketExists(bucketName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 创建 bucket
     * @param bucketName
     */
    public void makeBucket(String bucketName){
        try {
            boolean isExist = instance.bucketExists(bucketName);
            if(!isExist) {
                instance.makeBucket(bucketName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 文件上传
     * @param bucketName
     * @param objectName
     * @param filename
     */
    public void putObject(String bucketName, String objectName, String filename){
        try {
            instance.putObject(bucketName,objectName,filename,null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 文件上传
     * @param bucketName
     * @param objectName
     * @param stream
     */
    public void putObject(String bucketName, String objectName, InputStream stream){
        try {
            instance.putObject(bucketName,objectName,stream,new PutObjectOptions(stream.available(), -1));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 文件上传
     * @param bucketName
     * @param multipartFile
     */
    public void putObject(String bucketName, MultipartFile multipartFile, String filename) throws Exception{
        // PutObjectOptions，上传配置(文件大小，内存中文件分片大小)
        PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
        // 文件的ContentType
        putObjectOptions.setContentType(multipartFile.getContentType());
        instance.putObject(bucketName,filename,multipartFile.getInputStream(),putObjectOptions);
    }

    /**
     * 删除文件
     * @param bucketName
     * @param objectName
     */
    public void removeObject(String bucketName, String objectName){
        try {
            instance.removeObject(bucketName,objectName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 以流的形式获取一个文件对象
     *
     * @param bucketName 存储桶名称
     * @param objectName 存储桶里的对象名称
     * @return
     */
    public InputStream getObject(String bucketName, String objectName) throws Exception {
        boolean flag = bucketExists(bucketName);
        if (flag) {
            ObjectStat statObject = statObject(bucketName, objectName);
            if (statObject != null && statObject.length() > 0) {
                InputStream stream = instance.getObject(bucketName, objectName);
                return stream;
            }
        }
        return null;
    }

    /**
     * 以流的形式获取一个文件对象（断点下载）
     *
     * @param bucketName 存储桶名称
     * @param objectName 存储桶里的对象名称
     * @param offset     起始字节的位置
     * @param length     要读取的长度 (可选，如果无值则代表读到文件结尾)
     * @return
     */
    public InputStream getObject(String bucketName, String objectName, long offset, Long length) throws Exception {
        boolean flag = bucketExists(bucketName);
        if (flag) {
            ObjectStat statObject = statObject(bucketName, objectName);
            if (statObject != null && statObject.length() > 0) {
                InputStream stream = instance.getObject(bucketName, objectName, offset, length);
                return stream;
            }
        }
        return null;
    }

    /**
     * 获取对象的元数据
     *
     * @param bucketName 存储桶名称
     * @param objectName 存储桶里的对象名称
     * @return
     */
    public ObjectStat statObject(String bucketName, String objectName) throws Exception {
        boolean flag = bucketExists(bucketName);
        if (flag) {
            ObjectStat statObject = instance.statObject(bucketName, objectName);
            return statObject;
        }
        return null;
    }

    /**
     * 获取文件预览链接
     * @param bucketName
     * @param objectName
     * @param expires
     * @return
     * @throws Exception
     */
    public String presignedGetObject(String bucketName, String objectName, Integer expires) throws Exception {
        boolean flag = bucketExists(bucketName);
        String url = "";
        if (flag) {
            if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {
                throw new InvalidExpiresRangeException(expires,
                        "expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);
            }
            url = instance.presignedGetObject(bucketName, objectName, expires);
        }
        return url;
    }

    /**
     * 获取文件预览链接
     * @param bucketName
     * @param objectName
     * @return
     * @throws Exception
     */
    public String presignedGetObject(String bucketName, String objectName) throws Exception {
        return presignedGetObject(bucketName,objectName,DEFAULT_EXPIRY_TIME);
    }

    /**
     * 生成文件上传链接
     * @param bucketName
     * @param objectName
     * @param expires
     * @return
     * @throws Exception
     */
    public String presignedPutObject(String bucketName, String objectName, Integer expires) throws Exception {
        boolean flag = bucketExists(bucketName);
        String url = "";
        if (flag) {
            if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {
                throw new InvalidExpiresRangeException(expires,
                        "expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);
            }
            url = instance.presignedPutObject(bucketName, objectName, expires);
        }
        return url;
    }

    /**
     * 生成文件上传链接
     * @param bucketName
     * @param objectName
     * @return
     * @throws Exception
     */
    public String presignedPutObject(String bucketName, String objectName) throws Exception {
        return presignedPutObject(bucketName,objectName);
    }





}
